#include <Arduino.h>
#include "light/LightUdpClient.h"
#include "usb_cam/usb_camera.hpp"

const uint16_t streamPort = 8004;
const uint16_t serverPort = 8081;
const uint16_t localUdpPort = 2333;

LightUdpClient lightClient;
MsgHeader msgHeader;
UsbCamera usbCamera;

void debugOp();

void camGeneralOp();

void setCamChannelIndex();

void (*opTab[3])() = {debugOp, camGeneralOp, setCamChannelIndex};

void setup() {
    Serial.begin(115200);
    while (!Serial) {
    }
    // 初始化摄像头，并将设备属性中加入摄像头已有参数
    int attrCount = 4;
    String attr = String("version:1.0\n"
                         "cameraDev:true\n"
                         "devType:Camera\n"
                         // setCamChannelIndex函数指针的索引，摄像头类型的设备需要带此属性，用于light server回调
                         "setCamChannelIndexOpCode:3\n"
    );

    ConnectInfo connectInfo{};
    connectInfo.ssid = WIFI_SSID;
    connectInfo.passphrase = WIFI_PASSWORD;
    connectInfo.serverPort = serverPort;
    connectInfo.attrCount = attrCount;
    connectInfo.devAttr = attr.c_str();

#ifdef SERVER_HOST
    connectInfo.host = SERVER_HOST;
#endif
    connectInfo.userName = USER_NAME;
    connectInfo.passwd = PASS_WD;
    const IPAddress &address = lightClient.connectServer(connectInfo);
    // 控制通道连接成功才可打开 视频帧通道
    delay(1000);
    UsbCamera::begin(address, streamPort, localUdpPort);
}

void loop() {
    lightClient.startHeartbeat();
    int result = lightClient.readMsgHeader(&msgHeader);

    if (result == MSG_FAILED) {
        return;
    }
    int opCode = msgHeader.opCode;
    Serial.printf("cmdId:%d,opCode:%d\n", msgHeader.cmdIdVal, opCode);
    if (opCode > 2 || opCode < 0) {
        return;
    }
    opTab[opCode]();
}

void debugOp() {
    Serial.println("rec:" + lightClient.readStringUntil('\n'));
}

void camGeneralOp() {
    int functionIndex = lightClient.readInt('\n');
    if (functionIndex > -1 && functionIndex < 2) {
        (usbCamera.cameraOpt[functionIndex])();
    }
}

/**
 * light server回调设置摄像头通道
 * */
void setCamChannelIndex() {
    int channelIndex = lightClient.readInt('\n');
    UsbCamera::setChannelIndex(channelIndex);
}